require('dotenv').config({ path: '.env.development' });
// 多表名前缀配置（按长度倒序，确保优先匹配最长前缀）
const TABLE_PREFIXES = ['yh_hik_', 'yh_sys_', 'ly_sys_', 'ly_', 'sys_'];
// 数据库配置
const dbConfig = {
    type: process.env.DB_TYPE || 'mysql',
    host: process.env.DB_HOST || '127.0.0.1',
    port: process.env.DB_PORT || 3306,
    database: process.env.DB_DATABASE || 'nest_seed',
    username: process.env.DB_USERNAME || 'root',
    password: process.env.DB_PASSWORD || 'root',
    outputDir: 'src/modules',
};
//app.module.ts  插入的XXXModule在imports数组中哪个Module之后
const locationModuleName = 'OssModule'; //默认放在OssModule之后可自定义

const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const mysql = require('mysql2/promise');
// 新增：引入控制台输入模块
const readline = require('readline');
// 新增：创建控制台输入接口
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    terminal: true,
});


// 命名转换工具
const nameConvert = {
    camel: (str) => {
        return str.replace(/[_-]([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/^[A-Z]/, (letter) => letter.toLowerCase());
    },
    pascal: (str) => {
        const camelStr = str.replace(/[_-]([a-z])/g, (_, letter) => letter.toUpperCase());
        return camelStr.charAt(0).toUpperCase() + camelStr.slice(1);
    },
    kebab: (str) => {
        return str.replace(/_/g, '-').toLowerCase();
    },
};

// AppModule路径配置
const APP_MODULE_PATH = path.join(__dirname, 'src', 'app.module.ts');
console.log(`📌 检测到 AppModule 路径：${APP_MODULE_PATH}`);

// 新增：声明依赖用户输入的变量（先声明，在main中赋值）
let moduleSubDir, tableName, chineseName;
let effectiveTableName, entityClassName, entityFileName, kebabName, camelName;
let finalModuleDir, entityOutputDir, targetEntityPath;
let newModuleName, newModuleRelativePath, newModuleImportStmt;

// 新增：控制台提问工具函数（返回Promise处理异步输入）
function createQuestion(question) {
    return new Promise((resolve) => {
        rl.question(question, (answer) => {
            resolve(answer.trim()); // 去除输入前后空格
        });
    });
}

// 表名去前缀（核心：确保正确去除最长前缀）
function removeTablePrefix(tableName, prefixes) {
    for (const prefix of prefixes) {
        if (tableName.startsWith(prefix)) {
            return tableName.slice(prefix.length);
        }
    }
    return tableName;
}

// 确保目录存在
function ensureDirectoryExistence(dirPath) {
    if (!fs.existsSync(dirPath)) {
        fs.mkdirSync(dirPath, { recursive: true });
        console.log(`📂 创建目录：${dirPath}`);
    }
}

// 修复实体文件（移除@EntitySync相关，调整@Entity结构）
function fixEntityDefaultValues(entityPath, tableName) { // 新增tableName参数，用于@Entity表名
    try {
        let content = fs.readFileSync(entityPath, 'utf8');
        console.log(`🔧 开始修复实体文件 [${entityFileName}]（包含类名修正）...`);

        // 1. 调整@Entity结构：改为@Entity("实际表名", { synchronize: false })
        const entityDecoratorRegex = /@Entity\(([\s\S]*?)\)/g;
        if (entityDecoratorRegex.test(content)) {
            content = content.replace(
              entityDecoratorRegex,
              `@Entity("${tableName}", { synchronize: false })` // 关键修改：固定结构+原表名+关闭同步
            );
            console.log(`✅ 已调整@Entity结构为：@Entity("${tableName}", { synchronize: false })`);
        } else {
            throw new Error('未找到TypeORM的@Entity装饰器');
        }

        // 2. 关键修复1：修正实体类名（将基于原表名的类名替换为去前缀后的LogTest）
        const originalClassName = content.match(/export class (\w+)/)?.[1];
        if (originalClassName && originalClassName !== entityClassName) {
            content = content.replace(
              new RegExp(`export class ${originalClassName}`, 'g'),
              `export class ${entityClassName}`
            );
            console.log(`✅ 实体类名修正：${originalClassName} → ${entityClassName}`);
        }

        // 修复2：日期函数默认值
        content = content.replace(
          /default: \(\) => "\\\\"([A-Z_]+\(\d*\))\\\\\""/g,
          'default: "$1"'
        );

        // 修复3：数字默认值
        content = content.replace(
          /default: \(\) => "\\\\"(\d+)\\\\\""/g,
          'default: $1'
        );

        // 修复4：为updateAt字段添加onUpdate
        content = content.replace(
          /(@Column\("datetime", \{[\s\S]*?name: "updateAt"[\s\S]*?)(\n\s*}\))/g,
          '$1onUpdate: "CURRENT_TIMESTAMP(6)",\n$2'
        );

        // 修复5：调整id字段位置
        const idFieldMatch = content.match(/(@PrimaryGeneratedColumn[\s\S]*?;\n)/);
        if (idFieldMatch) {
            const idField = idFieldMatch[1];
            content = content.replace(idField, '');
            content = content.replace(
              /export class .*? \{/,
              `$&\n    ${idField.trim()}`
            );
        }

        fs.writeFileSync(entityPath, content, 'utf8');
        console.log(`✅ 实体文件修复完成：${entityFileName}`);
    } catch (error) {
        console.warn(`⚠️  实体文件修复失败：${error.message}，可手动调整类名和default属性`);
    }
}

// 检查数据库中目标表是否存在
async function checkTableExists() {
    let connection;
    try {
        connection = await mysql.createConnection({
            host: dbConfig.host,
            port: dbConfig.port,
            user: dbConfig.username,
            password: dbConfig.password,
            database: dbConfig.database,
            multipleStatements: false,
        });
        console.log(`📌 成功连接数据库：${dbConfig.database}（${dbConfig.host}:${dbConfig.port}）`);

        const [rows] = await connection.execute(
          `SELECT TABLE_NAME
             FROM information_schema.TABLES
             WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?`,
          [dbConfig.database, tableName],
        );

        const exists = rows.length > 0;
        if (!exists) {
            console.error(`\n❌ 数据表不存在：${tableName}（数据库：${dbConfig.database}）`);
        }
        return exists;
    } catch (error) {
        if (error.code === 'ER_ACCESS_DENIED_ERROR') {
            console.error(`\n❌ 数据库连接失败：用户名或密码错误`);
        } else if (error.code === 'ER_BAD_DB_ERROR') {
            console.error(`\n❌ 数据库不存在：${dbConfig.database}`);
        } else if (error.code === 'ETIMEDOUT' || error.code === 'EHOSTUNREACH') {
            console.error(`\n❌ 数据库连接超时：请检查 ${dbConfig.host}:${dbConfig.port} 是否可访问`);
        } else {
            console.error(`\n❌ 表存在性检查失败：${error.message}`);
        }
        return false;
    } finally {
        if (connection) {
            await connection.end();
            console.log(`📌 已关闭数据库连接`);
        }
    }
}

// 生成实体
async function generateEntityFromTable() {
    console.log(`\n🔧 正在检查数据表 [${tableName}] 是否存在...`);

    const tableExists = await checkTableExists();
    if (!tableExists) {
        process.exit(1);
    }

    console.log(`\n🔧 正在检查实体文件 [${entityFileName}]...`);
    if (fs.existsSync(targetEntityPath)) {
        console.log(`✅ 实体文件已存在：${targetEntityPath}，尝试修正类名...`);
        // 调用时传递tableName参数（关键修改）
        fixEntityDefaultValues(targetEntityPath, tableName);
        return;
    }

    console.log(`🔧 实体文件不存在，开始从数据表 [${tableName}] 生成...`);
    try {
        ensureDirectoryExistence(entityOutputDir);

        const generateCmd = [
            'typeorm-model-generator',
            `-h ${dbConfig.host}`,
            `-p ${dbConfig.port}`,
            `-d ${dbConfig.database}`,
            `-u ${dbConfig.username}`,
            `-x ${dbConfig.password}`,
            `-e ${dbConfig.type}`,
            `-o ${entityOutputDir}`,
            `-t "${tableName}"`,
            '--noConfig',
        ].join(' ');

        console.log(`📌 执行实体生成命令：${generateCmd}`);
        execSync(generateCmd, { stdio: 'pipe' });

        const generatedFiles = fs.readdirSync(entityOutputDir).filter(file =>
          file.endsWith('.ts') && !file.includes('index'),
        );

        if (generatedFiles.length === 0) {
            throw new Error(`未生成任何实体文件，请检查数据表 [${tableName}] 结构是否正常`);
        }

        const possibleFileNames = [
            tableName + '.ts',
            nameConvert.pascal(tableName) + '.ts',
            nameConvert.kebab(tableName) + '.ts',
        ].map(name => name.toLowerCase());

        let targetFile = null;
        for (const file of generatedFiles) {
            if (possibleFileNames.includes(file.toLowerCase())) {
                targetFile = file;
                break;
            }
        }
        if (!targetFile) targetFile = generatedFiles[0];

        // 重命名实体文件（确保文件名是log-test.entity.ts）
        const oldFilePath = path.join(entityOutputDir, targetFile);
        fs.renameSync(oldFilePath, targetEntityPath);
        console.log(`✅ 实体文件重命名：${targetFile} → ${entityFileName}`);

        // 调用时传递tableName参数（关键修改）
        fixEntityDefaultValues(targetEntityPath, tableName);

        // 删除多余文件
        generatedFiles.forEach(file => {
            if (file !== targetFile) {
                const filePath = path.join(entityOutputDir, file);
                fs.unlinkSync(filePath);
                console.log(`🗑️ 删除多余实体文件：${file}`);
            }
        });

        console.log(`✅ 实体生成完成！路径：${targetEntityPath}`);
    } catch (error) {
        console.error(`\n❌ 实体生成失败：${error.message}`);
        console.error(`📝 错误详情：${error.stdout?.toString() || error.stderr?.toString()}`);
        process.exit(1);
    }
}

// 解析实体字段
function parseEntityFields() {
    try {
        if (!fs.existsSync(targetEntityPath)) {
            throw new Error(`实体文件不存在：${targetEntityPath}`);
        }

        const entityContent = fs.readFileSync(targetEntityPath, 'utf8');
        const fieldRegex = /@Column\([\s\S]*?\)\s+(\w+):\s*(\w+);/g;
        const fields = [];
        let match;

        while ((match = fieldRegex.exec(entityContent)) !== null) {
            const fieldName = match[1];
            const fieldType = match[2];
            if (fieldName !== 'id') {
                fields.push({ name: fieldName, type: fieldType });
            }
        }

        if (fields.length === 0) {
            console.warn(`⚠️  未从实体文件中解析到字段，将生成默认查询逻辑`);
            return [];
        }

        console.log(`📊 解析到实体字段：${fields.map(f => `${f.name}(${f.type})`).join(', ')}`);
        return fields;
    } catch (error) {
        console.warn(`⚠️  解析实体字段失败：${error.message}，将生成默认查询逻辑`);
        return [];
    }
}

// 替换原有的addModuleToAppModule函数为以下代码
function addModuleToAppModule() {
    try {
        if (!fs.existsSync(APP_MODULE_PATH)) {
            throw new Error(`AppModule 文件不存在：${APP_MODULE_PATH}，请检查路径配置`);
        }

        let appModuleContent = fs.readFileSync(APP_MODULE_PATH, 'utf8');

        // 1. 清理可能存在的错误位置的导入和模块
        // 移除错误放在ConfigModule里的模块
        appModuleContent = appModuleContent.replace(new RegExp(`\n?\\s*${newModuleName}\\s*,?\n?`, 'g'), '');
        // 移除重复的导入语句
        appModuleContent = appModuleContent.replace(new RegExp(`${newModuleImportStmt}\n?`, 'g'), '');

        // 2. 检查是否已正确导入
        if (appModuleContent.includes(newModuleImportStmt) &&
          (appModuleContent.includes(`, ${newModuleName}`) || appModuleContent.includes(`[${newModuleName}`))) {
            console.log(`✅ AppModule 中已正确导入 ${newModuleName}，跳过添加`);
            return;
        }

        // 3. 导入语句插入：放在所有import语句之后，@Global()之前
        const globalDecoratorRegex = /@Global\(\)/;
        const globalMatch = appModuleContent.match(globalDecoratorRegex);

        if (globalMatch) {
            const insertPos = globalMatch.index;
            appModuleContent =
              appModuleContent.slice(0, insertPos) +
              `${newModuleImportStmt}\n\n` +
              appModuleContent.slice(insertPos);
            console.log(`✅ 已在@Global()前插入导入语句`);
        } else {
            // 找不到@Global()时，放在最后一个import语句后
            const lastImportRegex = /(import\s+{[\s\S]*?}\s+from\s+["'].+?["'];\s*)/g;
            const importMatches = [...appModuleContent.matchAll(lastImportRegex)];

            if (importMatches.length > 0) {
                const lastImport = importMatches[importMatches.length - 1];
                const insertPos = lastImport.index + lastImport[0].length;
                appModuleContent =
                  appModuleContent.slice(0, insertPos) +
                  `\n${newModuleImportStmt}` +
                  appModuleContent.slice(insertPos);
            } else {
                appModuleContent = `${newModuleImportStmt}\n\n${appModuleContent}`;
            }
            console.log(`✅ 已在最后一个import语句后插入导入语句`);
        }

        // 4. 模块注册：放在imports数组的末尾，OssModule之后
        const ossModuleRegex = new RegExp(`${locationModuleName},\\s*`);
        const ossMatch = appModuleContent.match(ossModuleRegex);

        if (ossMatch) {
            const insertPos = ossMatch.index + ossMatch[0].length;
            appModuleContent =
              appModuleContent.slice(0, insertPos) +
              `${newModuleName},\n        ` +
              appModuleContent.slice(insertPos);
            console.log(`✅ 已在${locationModuleName}后插入模块注册`);
        } else {
            // 找不到OssModule时，放在imports数组末尾
            const importsEndRegex = /(\s+)],/;
            const endMatch = appModuleContent.match(importsEndRegex);

            if (endMatch) {
                const [fullMatch, indent] = endMatch;
                appModuleContent = appModuleContent.replace(
                  fullMatch,
                  `${indent}    ${newModuleName},\n${fullMatch}`
                );
                console.log(`✅ 已在imports数组末尾插入模块注册`);
            } else {
                throw new Error(`未找到 imports 数组的正确位置`);
            }
        }

        // 写入修改后的AppModule
        fs.writeFileSync(APP_MODULE_PATH, appModuleContent, 'utf8');
        console.log(`✅ 成功将 ${newModuleName} 加入 AppModule 正确位置！`);
    } catch (error) {
        console.error(`\n⚠️  自动添加模块到 AppModule 失败：${error.message}`);
        console.error(`   请手动添加以下内容到 ${APP_MODULE_PATH}：`);
        console.error(`   1. 导入语句：在所有 import 语句之后、@Global() 之前添加：`);
        console.error(`      ${newModuleImportStmt}`);
        console.error(`   2. 模块注册：在 @Module({ imports: [ ... ] }) 数组中，OssModule 之后添加：`);
        console.error(`      ${newModuleName},`);
    }
}


// 生成CRUD代码
function generateCrudCode() {
    console.log(`\n🔧 正在生成 [${entityClassName}] 的 CRUD 代码...`);

    ensureDirectoryExistence(finalModuleDir);
    const entityFields = parseEntityFields();

    // 控制器代码
    const controllerContent = `import { Controller, Get, Post, Body, Patch, Param, Delete, Query } from "@nestjs/common";
import { ${entityClassName}Service } from "./${kebabName}.service";
import { ApiBearerAuth, ApiOperation, ApiTags } from "@nestjs/swagger";
import { ${entityClassName} } from "./entities/${entityFileName.replace('.ts', '')}";

@Controller("${moduleSubDir.replace(/\//g, '/')}")
@ApiTags("${chineseName}管理")
@ApiBearerAuth()
export class ${entityClassName}Controller {
  constructor(private readonly ${camelName}Service: ${entityClassName}Service) {}

  @Post()
  @ApiOperation({ summary: "创建${chineseName}" })
  create(@Body() createDto: Partial<${entityClassName}>) {
    return this.${camelName}Service.create(createDto);
  }

  @Get()
  @ApiOperation({ summary: "查询${chineseName}列表（分页）" })
  findAll(@Query() query: { page?: number; size?: number; [key: string]: any }) {
    return this.${camelName}Service.findAll(query);
  }

  @Get(":id")
  @ApiOperation({ summary: "查询${chineseName}详情" })
  findOne(@Param("id") id: string) {
    return this.${camelName}Service.findOne(+id);
  }

  @Patch(":id")
  @ApiOperation({ summary: "更新${chineseName}" })
  update(@Param("id") id: string, @Body() updateDto: Partial<${entityClassName}>) {
    return this.${camelName}Service.update(+id, updateDto);
  }

  @Delete("batch")
  @ApiOperation({ summary: "批量删除${chineseName}" })
  removeBatch(@Body() { ids }: { ids: number[] }) {
    return this.${camelName}Service.removeBatch(ids);
  }

  @Delete(":id")
  @ApiOperation({ summary: "删除${chineseName}" })
  remove(@Param("id") id: string) {
    return this.${camelName}Service.remove(+id);
  }
}`;

    // 服务代码
    let explicitWhereCode = '';
    if (entityFields.length > 0) {
        entityFields.forEach(field => {
            const { name: fieldName, type: fieldType } = field;
            if (['string', 'String', 'Date'].includes(fieldType)) {
                explicitWhereCode += `
    // ${fieldType}类型：模糊查询
    if (${fieldName} !== undefined && ${fieldName} !== null && ${fieldName} !== "") {
      where.${fieldName} = Like(\`%\${${fieldName}}%\`);
    }`;
            } else {
                explicitWhereCode += `
    // ${fieldType}类型：精确查询
    if (${fieldName} !== undefined && ${fieldName} !== null && ${fieldName} !== "") {
      where.${fieldName} = ${fieldName};
    }`;
            }
        });
    } else {
        explicitWhereCode = `
    // 默认循环逻辑（未解析到实体字段）
    Object.entries(params).forEach(([key, val]) => {
      if (val !== undefined && val !== null && val !== "") {
        if (typeof val === "string") {
          where[key] = Like(\`%\${val}%\`);
        } else {
          where[key] = val;
        }
      }
    });`;
    }

    const serviceContent = `import { Injectable, NotFoundException } from "@nestjs/common";
import { In, Like, Repository } from "typeorm";
import { ResultData } from "@/common/utils/result";
import { instanceToPlain } from "class-transformer";
import { InjectRepository } from "@nestjs/typeorm";
import { ${entityClassName} } from "./entities/${entityFileName.replace('.ts', '')}";

@Injectable()
export class ${entityClassName}Service {
  constructor(
    @InjectRepository(${entityClassName})
    private readonly ${camelName}Repo: Repository<${entityClassName}>,
  ) {}

  async create(createDto: Partial<${entityClassName}>) {
    const entity = this.${camelName}Repo.create(createDto);
    const saved = await this.${camelName}Repo.save(entity);
    return ResultData.ok(instanceToPlain(saved));
  }

  async findAll(query: { page?: number; size?: number; [key: string]: any; }) {
    const {
      page = 1,
      size = 15,
    } = query;

    const take = +size;
    const skip = (+page - 1) * take;
    const where = {
            // ...(status === 0 || status ? { status } : null),
            // ...(username ? { username: Like(\`%\${username}%\`) } : null)
        };
    const [row, total] = await this.${camelName}Repo.findAndCount({
      where,
      skip,
      take,
      order: { id: "DESC" },
    });

    return ResultData.ok({
      row: instanceToPlain(row),
      total,
      page: +page,
      size: take,
      pages: Math.ceil(total / take),
    });
  }

  async findOne(id: number) {
    const entity = await this.${camelName}Repo.findOneBy({ id });
    if (!entity) {
      throw new NotFoundException(\`${chineseName}（ID：\${id}）不存在\`);
    }
    return ResultData.ok(instanceToPlain(entity));
  }

  async update(id: number, updateDto: Partial<${entityClassName}>) {
    await this.${camelName}Repo.update(id, updateDto);
    return ResultData.ok(null, "更新成功");
  }

  async removeBatch(ids: number[]) {
    if (ids.length === 0) return ResultData.ok(null, "无数据需删除");
    const existCount = await this.${camelName}Repo.countBy({ id: In(ids) });
    return ResultData.ok(await this.${camelName}Repo.delete(ids), \`成功删除\${existCount}条${chineseName}数据\`);
  }

  async remove(id: number) {
    return ResultData.ok(await this.${camelName}Repo.delete(id), \`删除${chineseName}成功\`);
  }
}`;

    // 模块代码
    const moduleContent = `import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { ${entityClassName} } from "./entities/${entityFileName.replace('.ts', '')}";
import { ${entityClassName}Controller } from "./${kebabName}.controller";
import { ${entityClassName}Service } from "./${kebabName}.service";

@Module({
  imports: [TypeOrmModule.forFeature([${entityClassName}])],
  controllers: [${entityClassName}Controller],
  providers: [${entityClassName}Service],
  exports: [${entityClassName}Service, TypeOrmModule],
})
export class ${entityClassName}Module {}`;

    // 写入CRUD文件
    const filePaths = [
        { path: path.join(finalModuleDir, `${kebabName}.controller.ts`), content: controllerContent },
        { path: path.join(finalModuleDir, `${kebabName}.service.ts`), content: serviceContent },
        { path: path.join(finalModuleDir, `${kebabName}.module.ts`), content: moduleContent },
    ];

    filePaths.forEach(({ path: filePath, content }) => {
        fs.writeFileSync(filePath, content, 'utf8');
        console.log(`✅ 生成/更新CRUD文件：${filePath}`);
    });

    // 添加模块到AppModule
    console.log(`\n🔧 开始将 ${newModuleName} 加入 AppModule...`);
    addModuleToAppModule();
}

// 修改后的主流程：先控制台输入，再执行原有逻辑
async function main() {
    try {
        // 1. 控制台分步获取用户输入
        console.log('\n📝 代码生成工具 - 请依次输入配置信息');
        console.log('   提示：中文名称可直接回车，默认使用「userInfo」\n');

        moduleSubDir = await createQuestion('\x1b[33m1. 请输入模块路径名（示例：system/user-info）：\x1b[0m');
        tableName = await createQuestion('\x1b[33m2. 请输入要生成代码的数据库表名（示例：yh_sys_user_info）：\x1b[0m');
        const chineseNameInput = await createQuestion('\x1b[33m3. 请输入中文名称（示例：用户信息）：\x1b[0m');
        chineseName = chineseNameInput || 'userInfo'; // 处理默认值

        // 关闭输入接口，避免程序挂起
        rl.close();

        // 2. 原有参数校验逻辑
        if (!moduleSubDir || !tableName) {
            console.error('\n❌ 请输入「模块目录」和「数据表名」，可选中文名称，示例：');
            console.error('模块路径名：system/user-info');
            console.error('数据库表名：yh_sys_user_info');
            console.error('中文名称：日志测试\n');
            process.exit(1);
        }

        // 3. 计算依赖输入的变量（原顶部变量移至此处，补全完整）
        effectiveTableName = removeTablePrefix(tableName, TABLE_PREFIXES);
        console.log(`\n🔍 原表名：${tableName} → 去前缀后有效表名：${effectiveTableName}`);
        console.log(`🔍 中文名称：${chineseName}`);

        // 变量计算（确保实体类名为去前缀后的PascalCase）
        entityClassName = nameConvert.pascal(effectiveTableName); // 关键：ly_sys_log_test → log_test → LogTest
        entityFileName = `${nameConvert.kebab(effectiveTableName)}.entity.ts`; // log-test.entity.ts
        kebabName = nameConvert.kebab(effectiveTableName);
        camelName = nameConvert.camel(effectiveTableName);
        finalModuleDir = path.join(dbConfig.outputDir, moduleSubDir);
        entityOutputDir = path.join(finalModuleDir, 'entities');
        targetEntityPath = path.join(entityOutputDir, entityFileName);

        // 模块导入路径（包含modules层级）
        newModuleName = `${entityClassName}Module`;
        newModuleRelativePath = `@/modules/${moduleSubDir.replace(/\\/g, '/')}/${kebabName}.module`;
        newModuleImportStmt = `import { ${newModuleName} } from "${newModuleRelativePath}";`;

        // 4. 原有主流程逻辑
        console.log(`\n🚀 开始生成 [${tableName}]（去前缀→${effectiveTableName}）→ 模块[${moduleSubDir}] 相关代码...`);
        await generateEntityFromTable();
        generateCrudCode();
        console.log(`\n🎉 全部代码生成完成！`);
        console.log(`📁 最终模块目录：${finalModuleDir}`);
        console.log(`🗂️  实体文件（类名：${entityClassName}）：${targetEntityPath}`);
    } catch (err) {
        // 关闭输入接口避免异常时程序挂起
        rl.close();
        console.error(`\n❌ 执行失败：${err.message}`);
    }
}

main();